//@author A0078695H
/*

	Unit tests for Parser class

*/

#include "../parser.h"

TEST(parserTest, testTokenize) {
	vector<string> v = Parser::tokenize("a b", " ");
	EXPECT_EQ(v[0], "a");
	EXPECT_EQ(v[1], "b");
}

TEST(parserTest, testConcatenate) {
	vector<string> v;
	v.push_back("firsthalf");
	v.push_back("secondhalf");
	string str = Parser::concatenate(v);
	EXPECT_EQ(str, "firsthalf secondhalf");
}

TEST(parserTest, testIsBasicCommand) {
	EXPECT_EQ(Parser::isBasicCommand("notbasic"), -1);
	EXPECT_GE(Parser::isBasicCommand("add"), 0);
}

TEST(parserTest, testParseToCreatCmd) {
	// construct dummies to get a working parser
	Records dis = Records();
	Records tas = Records();
	dis.addData(Parser::stringToTask("myTask0"));
	tas.addData(Parser::stringToTask("myTask0"));
	Parser p = Parser();
	p.setDisplayRecords(&dis);
	p.setTaskListRecords(&tas);
	
	
	auto_ptr<Cmd> c = p.parse("add myTask1");
	CmdAdd add = *(static_cast<CmdAdd*>(c.get()));
	EXPECT_EQ(add.getCmdType(), cmdTypes::ADD); 
	
	c = p.parse("add ?");
	CmdHelp help = *(static_cast<CmdHelp*>(c.get()));
	EXPECT_EQ(help.getCmdType(), cmdTypes::HELP);
	
	c = p.parse("display");
	CmdDisplay display = *(static_cast<CmdDisplay*>(c.get()));
	EXPECT_EQ(display.getCmdType(), cmdTypes::DISPLAY);

	c = p.parse("delete 1");
	CmdDel del = *(static_cast<CmdDel*>(c.get()));
	EXPECT_EQ(del.getCmdType(), cmdTypes::DEL);

	c = p.parse("clear");
	CmdClear clear = *(static_cast<CmdClear*>(c.get()));
	EXPECT_EQ(clear.getCmdType(), cmdTypes::CLEAR);

	c = p.parse("sort start date");
	CmdSort sort = *(static_cast<CmdSort*>(c.get()));
	EXPECT_EQ(sort.getCmdType(), cmdTypes::SORT);
	
	c = p.parse("search task");
	CmdSearch search = *(static_cast<CmdSearch*>(c.get()));
	EXPECT_EQ(search.getCmdType(), cmdTypes::SEARCH);
	
	c = p.parse("filter task");
	CmdFilter filter = *(static_cast<CmdFilter*>(c.get()));
	EXPECT_EQ(filter.getCmdType(), cmdTypes::FILTER);
	
	c = p.parse("exit");
	CmdExit exit = *(static_cast<CmdExit*>(c.get()));
	EXPECT_EQ(exit.getCmdType(), cmdTypes::EXIT);

	c = p.parse("update 1");
	CmdUpdate update = *(static_cast<CmdUpdate*>(c.get()));
	EXPECT_EQ(update.getCmdType(), cmdTypes::UPDATE);

	c = p.parse("done 1");
	CmdDone done = *(static_cast<CmdDone*>(c.get()));
	EXPECT_EQ(done.getCmdType(), cmdTypes::DONE);

	c = p.parse("undone 1");
	CmdDone undone = *(static_cast<CmdDone*>(c.get()));
	EXPECT_EQ(undone.getCmdType(), cmdTypes::UNDONE);

	c = p.parse("help");
	CmdHelp help_master = *(static_cast<CmdHelp*>(c.get()));
	EXPECT_EQ(help_master.getCmdType(), cmdTypes::HELP);

	c = p.parse("undo");
	CmdUndo undo = *(static_cast<CmdUndo*>(c.get()));
	EXPECT_EQ(undo.getCmdType(), cmdTypes::UNDO);

	c = p.parse("redo");
	CmdUndo redo = *(static_cast<CmdUndo*>(c.get()));
	EXPECT_EQ(redo.getCmdType(), cmdTypes::REDO);

	c = p.parse("UNRECOGNIZABLE");
	CmdInvalid invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);

	// invalid add
	c = p.parse("add");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_TOO_FEW_ARG);

	c = p.parse("search");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_TOO_FEW_ARG);
	
	c = p.parse("delete");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_TOO_FEW_ARG);

	c = p.parse("update");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_TOO_FEW_ARG);
	
	c = p.parse("delete 2");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_IDX_INVALID);
	
	c = p.parse("done 2");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_IDX_INVALID);

	c = p.parse("update 2");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_IDX_INVALID);
	
	c = p.parse("delete abc");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_ARG_INVALID);
	
	c = p.parse("done abc");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_ARG_INVALID);

	c = p.parse("update abc");
	invalid = *(static_cast<CmdInvalid*>(c.get()));
	EXPECT_EQ(invalid.getCmdType(), cmdTypes::INVALID);
	EXPECT_EQ(invalid.getErrorType(), ErrorType::ERROR_ARG_INVALID);

	c = p.parse("delete 1-1");
	del = *(static_cast<CmdDel*>(c.get()));
	EXPECT_EQ(del.getCmdType(), cmdTypes::DEL);
	EXPECT_EQ(del.getIds().size(), 1);
	//EXPECT_EQ(del.getIds()[0], 1);

	c = p.parse("done 1-1");
	done = *(static_cast<CmdDone*>(c.get()));
	EXPECT_EQ(done.getCmdType(), cmdTypes::DONE);
	EXPECT_EQ(done.getIds().size(), 1);
	//EXPECT_EQ(done.getIds()[0], 1);


}

TEST(parserTest, testFindDates) {
	string s = "watch the day after tomorrow";
	vector<Date>* datesFound = new vector<Date>();
	vector<string>* notDates = new vector<string>();
	Parser::findDates(Parser::tokenize(s," "),datesFound,notDates);
	ASSERT_EQ(datesFound->size(), 1);
}

TEST(parserTest, testFindTwoDates) {
	string s = " test task1 tomorrow 9pm dec 27 3am";
	vector<Date>* datesFound = new vector<Date>();
	vector<string>* notDates = new vector<string>();
	Parser::findDates(Parser::tokenize(s," "),datesFound,notDates);
	ASSERT_EQ(datesFound->size(), 2);
}